package com.atguigu.mybatis.demo;

import com.atguigu.mybatis.bean.Employee;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

/**
 * Created by Smexy on 2023/10/23
 *
 JDBC框架，读写数据库。

           原生JDBC          Mybaits
 连接      Connection        SqlSession(内置连接)
 -------------------------------
 套路:
    ①创建SqlSession，连上数据库服务器
        借助 SqlSessionFactory去创建
    ②使用SqlSession把编写的sql发送给数据库服务器

 --------------------------------
    对象的创建
        最直接:  调用构造器。   A a = new A();

        某些情况下，构造方法的权限不是public，99%都无法调用！
        借助类提供的一些设计模式来创建对象。
            工厂模式:
                    A a = new AFactory().getA();

            建造者模式:
                    A a = new ABuilder().setArea(200m2).setStyle(精装修).build();

   --------------------------
    属性封装的规则:
        发送sql，查询数据:
             id  last_name  gender  email
             ------  ---------  ------  -------------
             1  Tom        male    Tom@163.com
        ①Mybatis根据sql语句的resultType，帮你调用Bean的空参构造器创建一个对象。
           Employee e =  new Employee();
        ②把每一行的每一列，赋值到Bean对象的属性中。
                Bean对象.setXxx(列值);
                Xxx是查询的列名。
                    e.setId(1);
                    e.setLast_name(tom);

    ------------------
        解决方式:
            第一种： 为Bean提供对应的setter。
                        不要选择！违背了非侵入式原则！
            第二种：  遵守非侵入式原则。实现功能时，只能修改自己功能所在的文件，不能侵犯其他文件。
                        自定义列名，让它符合Bean中的属性名的setter。
                    如果只是命名格式上遇到差异，内容上没有差异，可以通过配置，让Mybatis自动进行命名风格的转换。
                    让Mybaits遇到数据库的 下划线命名法，自动转换为Java的驼峰式命名法！

   -------------------
        当前套路的弊端:
            ①调用的方法是Mybatis提供的，某些方法，是不会对参数类型进行严格的约束。
                编译时，检查不出错误。
                运行时，可能报错！
            ②返回值类型，需要自己转换，麻烦！
                不是关键，可以通过传入泛型解决！

        解决：  自主替代。
                    我们只调用自己编写的方法。

   ------------------
        泛型方法的调用:
            泛型方法: <T> T 方法名(参数列表)
            调用的格式:  对象.<传入泛型的类型>方法名(参数);


 */
public class MybatisDemo1
{
    public static void main(String[] args) throws IOException {

        //1.构造SqlSessionFactory
        String resource = "mybatis.xml";   //定义mybatis的配置
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //2.获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //3.使用SqlSession 发送sql
        // 查询 employee的1号员工
        /*
             selectOne(String statement, Object parameter)
                statement: sql语句。 通过 namespace.id 来引用。
                        前提是： 编写了sql的xml文件，必须让mybatis知道。在mybatis的配置中去注册！
               Object parameter： sql中传入的参数。
         */
       /* Object one = sqlSession.selectOne("feichangbang.sql1", sqlSession);
        Employee employee = (Employee) one;*/
        Employee employee = sqlSession.<Employee>selectOne("feichangbang.sql1", sqlSession);

        System.out.println(employee);
        //4.关闭连接
        sqlSession.close();


    }
}
